package com.park.controller;

import com.park.common.annotation.Protected;
import com.park.common.bean.PayInputView;
import com.park.common.constant.IPlatformConstant;
import com.park.common.util.StrUtil;
import com.park.wx.WeiXinConnector;
import com.park.wx.http.HttpConnect;
import com.park.wx.util.ConfigUtil;
import com.park.wx.util.PayCommonUtil;
import com.park.wx.util.SignUtil;
import com.park.wx.util.XMLUtil;
import org.apache.log4j.Logger;
import org.jdom2.JDOMException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@RequestMapping("wxPay")
@Controller
public class WXPayController extends BaseController {
	
	private static Logger logger = Logger.getLogger(WXCoreController.class);
	
	//微信支付商户开通后 微信会提供appid和appsecret和商户号partner
		private static String appid = WeiXinConnector.APP_ID;//"wx86c89d3d834ee891";
		private static String appsecret = WeiXinConnector.SECRET;//"f0ea47515f733c537d196c4017a51c6e";
		private static String partner = WeiXinConnector.MCH_ID;
		//这个参数partnerkey是在商户后台配置的一个32位的key,微信商户平台-账户中心-账户设置-api安全
		private static String partnerkey = WeiXinConnector.KEY;
		//微信支付成功后通知地址 必须要求80端口并且地址不能带参数
		private static String notifyurl = "http://tingting.ngrok.cc/wxPay/asynNotify";																 // Key

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		//微信支付jsApi
		/*WxPayDto tpWxPay = new WxPayDto();
		tpWxPay.setOpenId(openId);
		tpWxPay.setBody("商品信息");
		tpWxPay.setOrderId(getNonceStr());
		tpWxPay.setSpbillCreateIp("127.0.0.1");
		tpWxPay.setTotalFee("0.01");
	    getPackage(tpWxPay);*/
	    
	    //扫码支付
	    /*WxPayDto tpWxPay1 = new WxPayDto();
	    tpWxPay1.setBody("商品信息");
	    tpWxPay1.setOrderId(getNonceStr());
	    tpWxPay1.setSpbillCreateIp("127.0.0.1");
	    tpWxPay1.setTotalFee("0.01");
		getCodeurl(tpWxPay1);*/

	}
	
	/**
	 * 获取请求预支付id报文
	 */
	@Protected
	@RequestMapping("wxPayPackage")
	public String wxPayPackage(PayInputView payInputView, Model model) throws JDOMException, IOException {
		
		String openId = payInputView.getOpenId(); //从session中获取
		// 1 参数
		// 订单号
		String orderId = payInputView.getOrderId();
		// 附加数据 原样返回
		String attach = "cxs";
		// 总金额以分为单位，不带小数点
		String totalFee = StrUtil.getMoney(payInputView.getTotalFee());
		
		// 订单生成的机器 IP
		String spbill_create_ip = payInputView.getSpbillCreateIp();
		// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
		String notify_url = notifyurl;
		String trade_type = "JSAPI";

		// ---必须参数
		// 商户号
		String mch_id = partner;
		// 随机字符串
		String nonce_str = StrUtil.getNonceStr();

		// 商品描述根据情况修改
		String body = payInputView.getBody();

		// 商户订单号
		String out_trade_no = orderId + IPlatformConstant.STR_LINE + System.currentTimeMillis() + IPlatformConstant.STR_LINE + getUserInfo2().getId();

		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		packageParams.put("appid", appid);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", body);
		packageParams.put("attach", attach);
		packageParams.put("out_trade_no", out_trade_no);

		// 这里写的金额为1 分到时修改
		packageParams.put("total_fee", totalFee);
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);

		packageParams.put("trade_type", trade_type);
		packageParams.put("openid", openId);
		String sign = PayCommonUtil.createSign("UTF-8", packageParams);
		packageParams.put("sign", sign);
		
		String requestXML = PayCommonUtil.getRequestXml(packageParams);
		logger.info("requestXML：" + requestXML);
		Map map = XMLUtil.doXMLParse(HttpConnect.httpsRequestStr(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML));

		String prepay_id = map.get("prepay_id").toString();
		logger.info("获取到的预支付ID：" + prepay_id);
		
		//获取prepay_id后，拼接最后请求支付所需要的package
		
		SortedMap<Object, Object> finalpackage = new TreeMap<Object, Object>();
		String timestamp = SignUtil.getTimeStamp();
		String packages = "prepay_id="+prepay_id;
		finalpackage.put("appId", appid);  
		finalpackage.put("timeStamp", timestamp);  
		finalpackage.put("nonceStr", nonce_str);  
		finalpackage.put("package", packages);  
		finalpackage.put("signType", "MD5");
		//要签名
		String finalsign = PayCommonUtil.createSign("UTF-8", finalpackage);
		
		String finaPackage = "\"appId\":\"" + appid + "\",\"timeStamp\":\"" + timestamp
		+ "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\""
		+ packages + "\",\"signType\" : \"MD5" + "\",\"paySign\":\""
		+ finalsign + "\"";

		logger.info("V3 jsApi package:"+finaPackage);
		model.addAttribute("package", finaPackage);
		return "";
	}
	
	//微信支付异步通知接口
	@RequestMapping("asynNotify")
    public void asynNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		response.setContentType("text/xml");
		String msgxml = this.getStreamResult(request, response);//xml数据
        Map map = XMLUtil.doXMLParse(msgxml);
        
        String result_code=(String) map.get("result_code");
        String out_trade_no  = (String) map.get("out_trade_no");
        String total_fee  = (String) map.get("total_fee");
        String sign  = (String) map.get("sign");
        Double amount = new Double(total_fee) / 100;//获取订单金额
        if(result_code.equals("SUCCESS")){
            //验证签名
            String fee_type  = (String) map.get("fee_type");
            String bank_type  = (String) map.get("bank_type");
            String cash_fee  = (String) map.get("cash_fee");
            String is_subscribe  = (String) map.get("is_subscribe");
            String nonce_str  = (String) map.get("nonce_str");
            String openid  = (String) map.get("openid");
            String return_code  = (String) map.get("return_code");
            String sub_mch_id  = (String) map.get("sub_mch_id");
            String time_end  = (String) map.get("time_end");
            String trade_type  = (String) map.get("trade_type");
            String transaction_id  = (String) map.get("transaction_id");
            String attach  = (String) map.get("attach");
            
            //需要对以下字段进行签名
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            packageParams.put("appid", appid);
            packageParams.put("bank_type", bank_type);
            packageParams.put("cash_fee", cash_fee);
            packageParams.put("fee_type", fee_type);
            packageParams.put("is_subscribe", is_subscribe);
            packageParams.put("mch_id", partner);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("openid", openid);
            packageParams.put("out_trade_no", out_trade_no);
            packageParams.put("result_code", result_code);
            packageParams.put("return_code", return_code);
            packageParams.put("sub_mch_id", sub_mch_id);
            packageParams.put("time_end", time_end); 
            packageParams.put("total_fee", total_fee); //用自己系统的数据：订单金额
            packageParams.put("trade_type", trade_type);
            packageParams.put("transaction_id", transaction_id);
            packageParams.put("attach", attach);

            String endsign = PayCommonUtil.createSign("UTF-8", packageParams);
            if(sign.equals(endsign)){//验证签名是否正确  官方签名工具地址：https://pay.weixin.qq.com/wiki/tools/signverify/
                //处理自己的业务逻辑
            	logger.info("支付成功!");
            	//response.getWriter().write(setXML("SUCCESS", "OK"));    //告诉微信已经收到通知了
            	BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(setXML("SUCCESS", "OK").getBytes());
                out.flush();
                out.close();
            }else{
            	logger.info("sign===>" + sign);
            	logger.info("endsign===>" + endsign);
            	logger.info("验证签名不正确");
            }
        }else{
        	response.getWriter().write(setXML("FAIL", "报文为空")); 
		}
    }
	
	public static String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }


	/*private void a(HttpServletRequest request, HttpServletResponse response){
		String no = this.request.getParameter("no");
		Orders findOrders = this.ordersService.findByNo(no);
		HttpSession session = this.request.getSession();
		User loginUser = (User) session.getAttribute("loginUser");

		JSONObject json = new JSONObject();
		if ((loginUser == null) || (loginUser.getId() == null)) {
			json.put("status", "0");
			json.put("message", "您未登陆或者登陆失效，请重新登陆");
			json.put("href", "../login.jsp");
		} else {
			User findUser = (User) this.userService.findById(User.class,
					loginUser.getId().intValue());
			if (findOrders == null) {
				json.put("status", "0");
				json.put("message", "订单不存在");
			} else if (findOrders.getUser().getId() != findUser.getId()) {
				json.put("status", "0");
				json.put("message", "没有权限");
			} else if (findUser.getBalance().doubleValue() < findOrders
					.getMoney().doubleValue()) {
				json.put("status", "0");
				json.put("message", "余额不足，请先充值");
			} else if (findOrders.getStatus().intValue() == 1) {
				json.put("status", "0");
				json.put("message", "该订单已付款，请不要重复提交支付");
			} else {
				*//*List<Kami> kamiList = this.kamiService.list(
				"from Kami where deleted=0 and status=0 and product.id="
						+ findOrders.getProductId(), 0, findOrders
						.getProductNum().intValue(), new Object[0]);
				if (kamiList.size() < findOrders.getProductNum().intValue()) {
					json.put("status", "0");
					json.put("message", "库存不足，请联系管理员");
				} *//*
				String productId = findOrders.getProductId();
				Product product = this.productService.findById(Product.class, Integer.valueOf(productId));
				int inventory = product.getInventory();
				int productNum = findOrders.getProductNum();
				if(inventory < productNum){
					json.put("status", "0");
					json.put("message", "库存不足，请联系管理员");
				}else {
					findUser.setBalance(Double.valueOf(findUser.getBalance()
							.doubleValue()
							- findOrders.getMoney().doubleValue()));
					if (findUser.getStatus().intValue() == 0) {
						findUser.setStatus(Integer.valueOf(1));
						findUser.setStatusDate(new Date());
					}
					this.userService.saveOrUpdate(findUser);
					product.setInventory(inventory-productNum);
					this.productService.saveOrUpdate(product);
					findOrders.setStatus(Integer.valueOf(1));
					Date date = new Date();
					String summary = "收货信息：<br/>"+"联系人:"+findUser.getContacts()+"<br/>联系地址:"+findUser.getAddress();
					*//*String summary = "卡密信息:<br/>";
					for (Kami kami : kamiList) {
						summary = summary + "卡号:" + kami.getNo() + ",密码:"
								+ kami.getPassword() + "<br/>";
						kami.setSaleTime(date);
						kami.setOrdersNo(findOrders.getNo());
						kami.setStatus(Integer.valueOf(1));
						this.kamiService.saveOrUpdate(kami);
					}*//*
					findOrders.setSummary(summary);
					findOrders.setPayDate(date);
					this.ordersService.saveOrUpdate(findOrders);

					Financial financial = new Financial();
					financial.setType(Integer.valueOf(0));
					financial.setMoney(Double.valueOf(-findOrders.getMoney()
							.doubleValue()));
					financial.setNo(String.valueOf(System.currentTimeMillis()));

					financial.setOperator(loginUser.getName());

					financial.setUser(findUser);

					financial.setCreateDate(new Date());
					financial.setDeleted(false);

					financial.setBalance(findUser.getBalance());
					financial.setPayment("余额付款");
					financial.setRemark("购买" + findOrders.getProductName());
					this.financialService.saveOrUpdate(financial);
					Config findConfig = (Config) this.configService.findById(
							Config.class, 1);

					String levelNos = findUser.getSuperior();
					if (!StringUtils.isEmpty(levelNos)) {
						String[] leverNoArr = levelNos.split(";");
						int i = leverNoArr.length - 1;
						for (int j = 1; i > 0; j++) {
							if (!StringUtils.isEmpty(leverNoArr[i])) {
								User levelUser = this.userService
										.getUserByNo(leverNoArr[i]);
								if (levelUser != null) {
									double commissionRate = 0.0D;
									if (j == 1)
										commissionRate = findConfig
												.getFirstLevel().doubleValue();
									else if (j == 2)
										commissionRate = findConfig
												.getSecondLevel().doubleValue();
									else if (j == 3) {
										commissionRate = findConfig
												.getThirdLevel().doubleValue();
									}

									double commissionNum = findOrders
											.getMoney().doubleValue()
											* commissionRate;
									levelUser.setCommission(Double
											.valueOf(levelUser.getCommission()
													.doubleValue()
													+ commissionNum));
									this.userService.saveOrUpdate(levelUser);

									Commission commission = new Commission();
									commission.setType(Integer.valueOf(1));
									commission.setMoney(Double
											.valueOf(commissionNum));
									commission.setNo(String.valueOf(System
											.currentTimeMillis()));

									commission.setOperator(loginUser.getName());

									commission.setUser(levelUser);

									commission.setCreateDate(date);
									commission.setDeleted(false);
									commission.setLevel(Integer.valueOf(j));
									commission.setRemark("第" + j + "级用户:编号【"
											+ loginUser.getNo() + "】购买商品奖励");
									this.commissionService
											.saveOrUpdate(commission);
								}
							}
							i--;
						}

					}

					json.put("status", "1");
					json.put("message", "付款成功");
					json.put("no", findOrders.getNo());
				}
			}
		}

		PrintWriter out = null;
		try {
			out = this.response.getWriter();
		} catch (IOException e) {
			e.printStackTrace();
		}
		out.print(json.toString());
		out.flush();
		out.close();
	}*/

}
